跳到主要内容

自定义 Rive RenderObject

扩展 RiveRenderObject 以执行更高级的操作。

通过扩展 RiveRenderObject,可以在运行时对 Rive 动画进行更精细的控制。这允许你重写底层方法如 advancebeforeDrawdraw,以获得更多控制并可选地执行额外操作。请参见下面的示例用法。

请注意,这是一个底层 API,在大多数情况下,最好使用 RiveAnimationRive 组件。

示例代码

以下是一个基本示例,演示如何使用自定义 RenderObject 绘制 Rive 动画并推进状态机。

import 'package:flutter/material.dart';
import 'package:rive/math.dart';
import 'package:rive/rive.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyRiveWidget(),
);
}
}

class MyRiveWidget extends StatefulWidget {
const MyRiveWidget({Key? key}) : super(key: key);

@override
State<MyRiveWidget> createState() => _MyRiveWidgetState();
}

class _MyRiveWidgetState extends State<MyRiveWidget> {
Artboard? _riveArtboard;

Future<void> _load() async {
// 你需要自行管理将控制器添加到画板,
// 不像 RiveAnimation 组件那样通过简单地提供状态机(或动画)名称来处理大量此类逻辑。
final file = await RiveFile.asset('assets/little_machine.riv');
final artboard = file.mainArtboard;
final controller = StateMachineController.fromArtboard(
artboard,
'State Machine 1',
);
artboard.addController(controller!);
setState(() => _riveArtboard = artboard);
}

@override
void initState() {
super.initState();
_load();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _riveArtboard == null
? const SizedBox()
: CustomRiveRenderObjectWidget(
artboard: _riveArtboard!,
fit: BoxFit.contain,
),
),
);
}
}

class CustomRiveRenderObjectWidget extends LeafRenderObjectWidget {
final Artboard artboard;
final BoxFit fit;
final Alignment alignment;

const CustomRiveRenderObjectWidget({
super.key,
required this.artboard,
this.fit = BoxFit.contain,
this.alignment = Alignment.center,
});

@override
RenderObject createRenderObject(BuildContext context) {
return CustomRiveRenderObject(artboard as RuntimeArtboard)
..artboard = artboard
..fit = fit
..alignment = alignment;
}

@override
void updateRenderObject(
BuildContext context, covariant CustomRiveRenderObject renderObject) {
renderObject
..artboard = artboard
..fit = fit
..alignment = alignment;
}

@override
void didUnmountRenderObject(covariant CustomRiveRenderObject renderObject) {
renderObject.dispose();
}
}

class CustomRiveRenderObject extends RiveRenderObject {
CustomRiveRenderObject(super.artboard) {
_artboardReference = artboard;
}

late final RuntimeArtboard _artboardReference;

@override
bool advance(double elapsedSeconds) {
// super 方法将更新动画并推进画板。
// 你可以自己推进画板,也可以调用 super 方法。
return _artboardReference.advance(elapsedSeconds, nested: true);
// 展示如何以两倍速度推进画板的示例。
return super.advance(elapsedSeconds * 2);
}

@override
void beforeDraw(Canvas canvas, Offset offset) {
// 在 `draw` 之前调用。可用于执行裁剪等操作。
super.beforeDraw(canvas, offset);
}

@override
void draw(Canvas canvas, Mat2D viewTransform) {
// 这里你可以接入绘制方法并执行自定义操作。
super.draw(canvas, viewTransform);
}
}

画板可以像往常一样通过 StateMachineController(或任何其他动画控制器)进行控制和配置。

示例用法

  • 在运行时动态更新组件颜色 - 使用自定义 Rive 渲染对象按名称更改形状的填充颜色。这对于颜色的不透明度正在动画中但需要在运行时更改颜色的情况非常有用。
  • 在 Flutter 中跟踪 Rive 组件 - 在运行时跟踪 Rive 组件的位置并覆盖 Flutter 组件或执行额外的绘制操作。

附加文档

有关 RenderObject 的更多信息,请参见官方 Flutter 示例: